AnnoyScript

Passing custom class object to web workers

· 4 minutes of read ·

views
Annoy level Time wasted[1] Solvable
Annoying bolt level 1 onAnnoying bolt level 2 onAnnoying bolt level 3 onAnnoying bolt level 4 offAnnoying bolt level 5 off 6h Kinda

Web workers are powerful sorcery in the battle against performance demons. When utilizing them, everyone gains a +10🛡️ defense bonus against senior devs and a +5🐎 boost to development stamina.

However, like every sword, they have two edges. One of these edges, hidden in the depths of MDN, can become a real pain in the ass when attempting to pass something more complex than an ordinary Object[2].

Let's take a look at the simple planWorker.ts code:

onmessage = function (e: MessageEvent): void {
const x = e.data.x as number;
const y = e.data.y as number;

const layer = new Layer(x, y); // layer type is Layer

postMessage({ layer: layer });
};

The worker gathers the data and then creates a new Layer with the given arguments. After the work is done, the new layer is sent back and can be accessed as e.data.layer.

Now, let's examine the process method of the Frame class that created this web worker in attempt to push the returned object named layer into the layers property in its class:

export default class Frame {
layers: Layer[] = [];

public process({ x, y }: Coords): void {
const worker = new Worker(
new URL("../utils/planWorker.ts", import.meta.url)
);

worker.onmessage = (e: MessageEvent) => {
const layer: Layer = e.data.layer; // layer type is Layer, right?

this.layers.push(layer);
worker.terminate();
};

worker.postMessage({
x: x,
y: y,
});
}
}

How pleasantly surprising it was to discover that suddenly methods working on the layers array couldn't access some of the methods from the Layer class. Well I think that means it's...

Annoying time logo

After many hours of debugging, I discovered this GitHub question and realized that, unlike every other time, the fault was not on my side.

The issue lay within the web worker messaging system.

Caution

If your custom class contains something more then just properties then buckle your seatbelt Dorothy, 'cause they are going bye-bye![3]. The structured cloning algorithm used by web worker message system will ignore all of yours:

The solution to handle this ✨feature✨ is to either construct new object properties to maintain the current state of the original class or utilize JSON. However, the loss of methods may be unacceptable for some, thus making web workers less than ideal for handling more complex custom class objects[4].






  1. I learn something for sure, but you know... I could spend that time more productive, like watching Adventure Time instead. ↩︎

  2. Web workers can also pass Array, ArrayBuffer, Boolean, DataView, Date, Map, Number, Primitive types, except symbol, RegExp, Set, String and TypedArray. ↩︎

  3. Reference to Matrix movie. ↩︎

  4. Other constrain may be the fact that all objects are copied not shared when used by messages system. Sharing data is possible, but not with the objects. ↩︎

AnnoyancesTypeScript